/*
 * Channel.h
 *
 *  Created on: Jul 12, 2016
 *      Author: Lucifer
 */

#ifndef BFX_SELECTIONKEY_H_
#define BFX_SELECTIONKEY_H_

#include "./Common.h"
#include "./RCObject.h"
#include "./SelectableChannel.h"

#include <boost/thread.hpp>

namespace BFX {

class Selector;

class SelectionKey: public RCObject {
public:
	enum {
		OP_READ = 1,	/// bit for read operation.
		OP_WRITE = 2,	/// bit for write operation.
		OP_CONNECT = 4,	/// bit for connect operation.
		OP_ACCEPT = 8	/// bit for accept operation.
	};

public:
	SelectionKey(SelectableChannel* channel, Selector* selector) :
			_valid(true), _channel(channel), _selector(selector), _interestOps(0), _callback(
					nullptr), _readyOps(0) {
	}
	virtual ~SelectionKey() {
	}

	/// Returns the channel for which this key was created.
	SelectableChannel* getChannel() const {
		return _channel;
	}
	/// Returns the selector for which this key was created.
	Selector* getSelector() const {
		return _selector;
	}

	/// Determine whether or not this key is valid.
	bool isValid() const {
		return _valid;
	}
	/// Marks this key is invalidate.
	void invalidate() {
		_valid = false;
	}
	/// Requests that the registration of this key's channel with its selector be cancelled.
	void cancel();

	/// Sets this key's interest set to the given value.
	void setInterestOps(int ops, SelectCallback callback) {
		BFX_ASSERT(isValid());
		BFX_ASSERT((ops & ~getChannel()->getValidOps()) == 0);
		// XXX Place ops into pollfd array
		_interestOps = ops;
		_callback = callback;
	}
	void notify() {
		_callback(this);
	}
	/// Retrieves this key's interest set.
	int getInterestOps() const {
		return _interestOps;
	}
	/// Retrieves this key's ready-operation set.
	int getReadyOps() const {
		BFX_ASSERT(isValid());
		return _readyOps;
	}
	void setReadyOps(int ops) {
		// XXX should be protected
		BFX_ASSERT(isValid());
		_readyOps = ops;
	}
	/// Tests whether this key's channel is ready for reading.
	bool isReadable() const {
		return !!(getReadyOps() & OP_READ);
	}
	/// Tests whether this key's channel is ready for writing.
	bool isWritable() const {
		return !!(getReadyOps() & OP_WRITE);
	}
	/// Tests whether this key's channel has either finished.
	bool isConnectable() const {
		return !!(getReadyOps() & OP_CONNECT);
	}
	/// Tests whether this key's channel is ready to accept a new socket.
	bool isAcceptable() const {
		return !!(getReadyOps() & OP_ACCEPT);
	}

private:
	volatile bool _valid;

	SelectableChannel* _channel;
	Selector* _selector;
	int _interestOps;
	SelectCallback _callback;
	int _readyOps;
};

} /* namespace BFX */

#endif /* BFX_SELECTIONKEY_H_ */
